#include "udpwork.h"
#include "utils.h"
#include <QTime>
#include "MessageErrorException.h"
#include "socketwork.h"
UDPWork::UDPWork(QObject *parent) : QObject(parent)
{
    udp_socket = new QUdpSocket(this);
    udp_socket->bind(localAddress, 12345);
    shakeStringFrom = "I am MRI System Hololens2";
    shakeStringTo =  "I am MRI System PC";
    connect(udp_socket, &QUdpSocket::readyRead, this, &UDPWork::receive_data_slot);
}

void UDPWork::send_Broadcast_slot()
{
    try
    {
        QByteArray datagram = shakeStringTo.toLocal8Bit();
        udp_socket->writeDatagram(datagram, datagram.size(), QHostAddress::Broadcast, 24510);
     }
    catch (const std::exception& e)
    {
        emit update_textBrowser_signal(QString::fromUtf8(e.what()));
    }

}

void UDPWork::send_Message_slot(QString meg)
{
    try
    {
        QByteArray datagram = meg.toLocal8Bit();
        udp_socket->writeDatagram(datagram, remoteAddress , 24510);
     }
    catch (const std::exception& e)
    {
        emit update_textBrowser_signal(QString::fromUtf8(e.what()));
    }

}

void UDPWork::receive_data_slot()
{
    while (udp_socket->hasPendingDatagrams())
    {
//        QByteArray datagram;
//        datagram.resize(udp_socket->pendingDatagramSize());
//        udp_socket->readDatagram(datagram.data(), datagram.size());

        QByteArray data = udp_socket->readAll();
        receive_bytes.append(data);

        try
        {
            const int index = unpack_receive_data();
            if (index > 0)
            {
                receive_bytes.remove(0, index);
            }
        }
        catch (MessageErrorException &)
        {
            receive_bytes.clear();
            emit update_textBrowser_signal("Receive Message Header error, auto disconnect socket");
        }
    }
}
//void UDPWork::receive_data_slot()
//{
//    while (udp_socket->hasPendingDatagrams())
//    {
////        QByteArray datagram;
////        datagram.resize(udp_socket->pendingDatagramSize());
////        udp_socket->readDatagram(datagram.data(), datagram.size());

//        QByteArray data = udp_socket->readAll();
//        receive_bytes.append(data);

//        try
//        {
//            const int index = unpack_receive_data();
//            if (index > 0)
//            {
//                receive_bytes.remove(0, index);
//            }
//        }
//        catch (MessageErrorException &)
//        {
//            receive_bytes.clear();
//            emit update_textBrowser_signal("Receive Message Header error, auto disconnect socket");
//        }
//    }
//}
int UDPWork::unpack_receive_data()
{
    int index = 0;

    while (true)
    {
        if (index + MSG_HEADER_LENGTH + MSG_TOTAL_LENGTH + MSG_TYPE_LENGTH >= receive_bytes.length())
        {
            break;
        }
        else
        {
            QByteArray msg_header = receive_bytes.mid(index, MSG_HEADER_LENGTH);

            if (static_cast<unsigned char>(msg_header.at(0)) != 0x00 ||
                static_cast<unsigned char>(msg_header.at(1)) != 0xff ||
                static_cast<unsigned char>(msg_header.at(2)) != 0x0f ||
                static_cast<unsigned char>(msg_header.at(3)) != 0x00)
            {
                throw MessageErrorException(-1);
            }

            int msg_length = Bytes2Number<int>(receive_bytes.mid(index + MSG_HEADER_LENGTH, MSG_TOTAL_LENGTH));

            if (msg_length + index + MSG_HEADER_LENGTH + MSG_TOTAL_LENGTH > receive_bytes.length())
            {
                break;
            }

            ClientMsgType msg_type = ClientMsgType(
                Bytes2Number<int>(receive_bytes.mid(index + MSG_HEADER_LENGTH + MSG_TOTAL_LENGTH, MSG_TYPE_LENGTH)));

            QByteArray msg_data = receive_bytes.mid(index + MSG_HEADER_LENGTH + MSG_TOTAL_LENGTH + MSG_TYPE_LENGTH,
                                                    msg_length - MSG_TYPE_LENGTH);

            index += msg_length + MSG_HEADER_LENGTH + MSG_TOTAL_LENGTH;

            if (msg_type == ClientSendShakeHand)
            {
                handle_shakehand_message(msg_data);
            }
            else if (msg_type == ClientSendPreview)
            {
                handle_preview_message(msg_data);
            }

        }
    }

    return index;
}

void UDPWork::handle_preview_message(const QByteArray &bytes)
{

    int message_length = Bytes2Number<int>(bytes.mid(0, 4));

    QByteArray message_bytes = bytes.mid(4, message_length);
    QPixmap pixmap;

    if (!pixmap.loadFromData(message_bytes))
    {
        return;
    }

    emit preview_image_signal(pixmap.copy());
}

void UDPWork::handle_shakehand_message(const QByteArray &bytes)
{

    QString remoteIP = QString(bytes);

    emit detain_ClientIP_signal(remoteIP);
    remoteAddress = QHostAddress(remoteIP);

}

void UDPWork::Update_IP_slot(QString ip)
{
    localIP = ip;
}
